<!-- BaseInput.vue -->
<script setup>
import { computed, ref, useAttrs, watchEffect } from 'vue';
import { useForm } from './useForm';

const props = defineProps({
  modelValue: {
    type: [String, Number, Date],
    default: ''
  },
  type: {
    type: String,
    default: 'text',
    validator: value =>
        ['text', 'password', 'email', 'number', 'tel', 'url', 'search', 'date', 'time', 'datetime-local'].includes(value)
  },
  label: String,
  placeholder: String,
  disabled: Boolean,
  readonly: Boolean,
  required: Boolean,
  min: [Number, String, Date],
  max: [Number, String, Date],
  step: [Number, String],
  minlength: Number,
  maxlength: Number,
  pattern: String,
  validate: Function,
  error: String,
  showCounter: Boolean,
  size: {
    type: String,
    default: 'default',
    validator: value => ['small', 'default', 'large'].includes(value)
  },
  bordered: {
    type: Boolean,
    default: true
  },
  rounded: Boolean
});

const emit = defineEmits([
  'update:modelValue',
  'blur',
  'focus',
  'change',
  'keypress',
  'keydown',
  'keyup',
  'clear'
]);

// 表单上下文（如果使用Form组件）
const formContext = useForm();

// 表单输入ID（用于无障碍访问）
const inputId = computed(() => props.id || `input-${Math.random().toString(36).substr(2, 9)}`);

// 本地错误状态
const localError = ref('');
const hasError = computed(() => props.error || localError.value);
const isDisabled = computed(() => formContext?.disabled.value || props.disabled);

// 处理输入值
const handleInput = (event) => {
  let value = event.target.value;

  // 类型转换
  if (props.type === 'number') {
    value = Number(value);
  }

  emit('update:modelValue', value);
  validateInput(value);
  emit('change', value);
};

// 处理清空操作
const clearInput = () => {
  emit('update:modelValue', '');
  emit('clear');
  validateInput('');
};

// 验证输入
const validateInput = (value) => {
  let errorMsg = '';

  // 基础验证
  if (props.required && !value) {
    errorMsg = formContext?.requiredMessage.value || '此字段为必填项';
  } else if (props.minlength && value?.length < props.minlength) {
    errorMsg = `长度至少为 ${props.minlength} 个字符`;
  } else if (props.maxlength && value?.length > props.maxlength) {
    errorMsg = `长度不能超过 ${props.maxlength} 个字符`;
  } else if (props.pattern && value && !new RegExp(props.pattern).test(value)) {
    errorMsg = formContext?.patternMessage.value || '格式不正确';
  }

  // 自定义验证
  if (!errorMsg && props.validate) {
    const customError = props.validate(value);
    if (typeof customError === 'string') {
      errorMsg = customError;
    }
  }

  localError.value = errorMsg;
  return !errorMsg;
};

// 暴露验证API
const validate = () => validateInput(props.modelValue);

defineExpose({
  validate,
  clear: clearInput,
  focus: () => inputRef.value?.focus(),
  blur: () => inputRef.value?.blur()
});

// 模板引用
const inputRef = ref(null);

// 监听表单上下文的验证
watchEffect(() => {
  if (formContext?.validateAll.value) {
    validate();
  }
});
</script>

<template>
  <div
      class="input-container"
      :class="[
      size,
      {
        'has-error': hasError,
        'is-disabled': isDisabled,
        'is-readonly': readonly,
        'no-border': !bordered,
        'rounded': rounded
      }
    ]"
  >
    <label
        v-if="label"
        :for="inputId"
        class="input-label"
        :class="{ required }"
    >
      {{ label }}
    </label>

    <div class="input-wrapper">
      <!-- 前缀内容 -->
      <div v-if="$slots.prefix" class="input-prefix">
        <slot name="prefix"></slot>
      </div>

      <!-- 输入框 -->
      <input
          :id="inputId"
          ref="inputRef"
          :type="type"
          class="base-input"
          :value="modelValue"
          @input="handleInput"
          @blur="$emit('blur', $event)"
          @focus="$emit('focus', $event)"
          @keypress="$emit('keypress', $event)"
          @keydown="$emit('keydown', $event)"
          @keyup="$emit('keyup', $event)"
          :placeholder="placeholder"
          :disabled="isDisabled"
          :readonly="readonly"
          :required="required"
          :min="min"
          :max="max"
          :step="step"
          :minlength="minlength"
          :maxlength="maxlength"
          :pattern="pattern"
          :aria-invalid="hasError ? 'true' : null"
          :aria-describedby="hasError ? `${inputId}-error` : null"
          v-bind="$attrs"
      />

      <!-- 清空按钮 -->
      <button
          v-if="modelValue && type !== 'password' && !isDisabled"
          class="clear-button"
          type="button"
          aria-label="清空输入内容"
          @click="clearInput"
      >
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none">
          <path d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" fill="currentColor"/>
        </svg>
      </button>

      <!-- 显示/隐藏密码 -->
      <button
          v-if="type === 'password'"
          class="password-toggle"
          type="button"
          aria-label="显示/隐藏密码"
          @click="type = type === 'password' ? 'text' : 'password'"
      >
        <svg v-if="type === 'password'" width="16" height="16" viewBox="0 0 24 24">
          <path d="M12 5C5.64 5 1 12 1 12s4.64 7 11 7 11-7 11-7-4.64-7-11-7zm0 11c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z" fill="currentColor"/>
          <path d="M12 8a4 4 0 100 8 4 4 0 000-8z" fill="currentColor"/>
        </svg>
        <svg v-else width="16" height="16" viewBox="0 0 24 24">
          <path d="M1 9l2.5 2.5M8 13l3-3-7 7h14v-6l-3 3M11 6l-1 1m-7.18 0L20 18.18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
        </svg>
      </button>

      <!-- 后缀内容 -->
      <div v-if="$slots.suffix && type !== 'password'" class="input-suffix">
        <slot name="suffix"></slot>
      </div>
    </div>

    <!-- 反馈信息 -->
    <div class="feedback">
      <div
          v-if="hasError"
          :id="`${inputId}-error`"
          class="error-message"
          role="alert"
      >
        {{ error || localError }}
      </div>
      <div v-else-if="showCounter" class="counter">
        {{ modelValue?.toString().length || 0 }} / {{ maxlength }}
      </div>
      <div v-else class="hint">
        <slot name="hint"></slot>
      </div>
    </div>
  </div>
</template>

<style scoped>
.input-container {
  --input-height: 32px;
  --font-size: 14px;
  --padding-x: 12px;
  --border-radius: 4px;
}

.input-container.small {
  --input-height: 28px;
  --font-size: 13px;
  --padding-x: 10px;
  --border-radius: 3px;
}

.input-container.large {
  --input-height: 40px;
  --font-size: 16px;
  --padding-x: 14px;
  --border-radius: 6px;
}

.input-label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--font-size);
  color: var(--input-label-color, #606266);
  font-weight: 500;
}

.input-label.required::after {
  content: '*';
  color: #f56c6c;
  margin-left: 4px;
}

.input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.base-input {
  width: 100%;
  height: var(--input-height);
  padding: 0 var(--padding-x);
  font-size: var(--font-size);
  color: var(--input-text-color, #606266);
  background-color: #fff;
  border: 1px solid var(--input-border-color, #dcdfe6);
  border-radius: var(--border-radius);
  transition:
      border-color 0.15s ease-in-out,
      box-shadow 0.15s ease-in-out;
}

.base-input:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.no-border .base-input {
  border: none;
  border-bottom: 1px solid var(--input-border-color, #dcdfe6);
  border-radius: 0;
}

.rounded .base-input {
  border-radius: 30px;
}

.input-prefix,
.input-suffix {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  pointer-events: none;
  color: var(--input-affix-color, #c0c4cc);
  z-index: 1;
}

.input-prefix {
  left: var(--padding-x);
}

.input-suffix {
  right: var(--padding-x);
}

.base-input:not(:placeholder-shown) + .clear-button {
  opacity: 1;
  pointer-events: all;
}

.clear-button,
.password-toggle {
  position: absolute;
  right: var(--padding-x);
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: #c0c4cc;
  transition: opacity 0.2s;
  opacity: 0;
  pointer-events: none;
}

.clear-button:hover,
.password-toggle:hover {
  color: #909399;
}

.password-toggle {
  opacity: 1;
  pointer-events: all;
  right: calc(var(--padding-x) + 26px);
}

.base-input:focus ~ .clear-button {
  opacity: 1;
  pointer-events: all;
}

/* 禁用状态 */
.is-disabled .base-input {
  background-color: #f5f7fa;
  cursor: not-allowed;
  opacity: 0.7;
}

/* 错误状态 */
.has-error .base-input {
  border-color: #f56c6c;
}

.has-error .base-input:focus {
  border-color: #f56c6c;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2);
}

.has-error .input-label {
  color: #f56c6c;
}

/* 反馈区域 */
.feedback {
  min-height: 22px;
  margin-top: 4px;
}

.error-message {
  font-size: calc(var(--font-size) - 2px);
  color: #f56c6c;
}

.counter {
  font-size: calc(var(--font-size) - 2px);
  color: #c0c4cc;
  text-align: right;
}

.hint {
  font-size: calc(var(--font-size) - 2px);
  color: #909399;
}
</style>